//********************************************************************************
//
// File :           ph02_enum_sort.cpp
//
// Description :    enum_sort arrays
//
// Dependencies:    
//
// Author :         UlMonkey1987( WU Kan )
//
// Stu NO. :        2010212404
//
// Date :           2011-4-17
//
//********************************************************************************

#include <iostream>
#include <fstream>
#include <iomanip>

#include <cstdlib>
#include <cmath>
#include <ctime>

#include <string>

using namespace std;

// bool readData( const string& strTestDataPath, long* pNum, unsigned long numN )
bool readData( const string& strTestDataPath, long* pNum, unsigned long numN )
{
    if ( 0 == pNum ) return false;

    ifstream fin( strTestDataPath.c_str(), iostream::binary );

    char* pByteData = ( char* ) pNum;

    fin.read( pByteData, numN * sizeof( long ) );

    return true;
}
//

// unsigned long calc_rank( const long* pNum, const unsigned long numN, const unsigned long curIndex )
unsigned long calc_rank( const long* pNum, const unsigned long numN, const unsigned long curIndex )
{
    unsigned long ret_rank = 0;

    for ( unsigned long i = 0; i < numN; i ++ )
    {
        if ( ( pNum[i] < pNum[curIndex] ) || ( i < curIndex && pNum[i] == pNum[curIndex] ) )
            ret_rank ++;
    }

    return ret_rank;
}
//

int main( int argc, char* argv[] )
{
    if ( argc < 4 )
    {
        cout << "error : lack args." << endl;
        cout << "usage : " << "<program_name>" << " <test_data_path> <n> <output_file_path>." << endl;
        return 1;
    }

    string strTestDataPath = string( argv[1] );     // data src path
    unsigned long numN = atoi( argv[2] );      // numN
    string strOutPath = string( argv[3] );      // output path

//     // args for test
//     string strTestDataPath = "";
//     unsigned long numN = 100;
//     string strOutPath = "result.txt";
//     // ! args for test

    clock_t timeStart, timeEnd;                 // start time, end time
    double timeCost;                        // duration time

    long* pNum = new long[numN];
    readData( strTestDataPath, pNum, numN );
//     for ( unsigned long i = 0; i < numN; i ++ )
//         pNum[i] = numN - i;

    long* pNumRank = new long[numN];

    timeStart = clock();

    pNumRank = new long[numN];                               // temp count
    for ( unsigned long i = 0; i < numN; i ++ )
    {
        unsigned long rankIndex = calc_rank( pNum, numN, i );        // rank current data element

        pNumRank[i] = rankIndex;                                            // set current data element rank
    }

    // rearrange data according to the ranks
    long* pNumTemp = new long[numN];
    for ( unsigned long i = 0; i < numN; i ++ )
        pNumTemp[i] = pNum[i];

    for ( unsigned long i = 0; i < numN; i ++ )
    {
        unsigned long dstIndex = pNumRank[i];
        pNum[dstIndex] = pNumTemp[i];
    }
    delete []pNumTemp; pNumTemp = 0;
    // ! rearrange data according to the ranks

    timeEnd = clock();
    timeCost = ( timeEnd - timeStart ) * 1.0 / ( CLOCKS_PER_SEC );

//     for ( unsigned long i = 0; i < numN; i ++ )
//     {
//         cout << pNum[i];
//         if ( numN - 1 != i ) cout << ",";
//     }
//     cout << endl;
// 
//     cout << endl << "cost time : " << timeCost << endl;

    delete []pNum; pNum = 0;

    ofstream fout( strOutPath.c_str(), ios::app );

    fout << "non_cluster\t" << strTestDataPath << "\t" << "enum_sorting\t" << numN << "\t" << setprecision( 2 ) << timeCost << "\n";

    delete []pNumRank; pNumRank = 0;

    cout << endl << "non_cluster " << strTestDataPath << " " << "enum_sorting " << numN << " " << setprecision( 2 ) << timeCost << endl;

    // system( "pause" );

    return 0;
}
